Põhjalik juhend TypeScripti vahevara mõistmiseks ja rakendamiseks Express.js rakendustes. Avastage täiustatud tüübimustreid tugeva ja hooldatava koodi jaoks.
TypeScripti vahevara: Expressi vahevara tüüpide mustrite valdamine
Express.js, minimalistlik ja paindlik Node.js veebirakenduste raamistik, võimaldab arendajatel luua tugevaid ja skaleeritavaid API-sid ja veebirakendusi. TypeScript täiustab Expressi staatilise tüübi lisamisega, parandades koodi hooldatavust ja tuvastades vead varakult. Vahevara funktsioonid on Expressi nurgakivi, mis võimaldab teil pealt kuulata ja töödelda päringuid enne, kui need jõuavad teie marsruudi halduriteni. See artikkel uurib täiustatud TypeScripti tüübimustreid Expressi vahevara määratlemiseks ja kasutamiseks, suurendades tüübikindlust ja koodi selgust.
Expressi vahevara mõistmine
Vahevara funktsioonid on funktsioonid, millel on juurdepääs päringu objektile (req), vastuse objektile (res) ja järgmisele vahevara funktsioonile rakenduse päringu-vastuse tsüklis. Vahevara funktsioonid saavad teha järgmisi toiminguid:
- Teostada mis tahes koodi.
- Teha muudatusi päringu ja vastuse objektides.
- Lõpetada päringu-vastuse tsükkel.
- Kutsuda välja järgmine vahevara funktsioon magasinis.
Vahevara funktsioone täidetakse järjestikku, kui need lisatakse Expressi rakendusele. Levinud kasutusjuhud vahevarale on järgmised:
- Päringute logimine.
- Kasutajate autentimine.
- Juurdepääsu autoriseerimine ressurssidele.
- Päringu andmete valideerimine.
- Vigade käsitlemine.
Põhiline TypeScripti vahevara
Põhilises TypeScripti Expressi rakenduses võib vahevara funktsioon välja näha selline:
import { Request, Response, NextFunction } from 'express';
function loggerMiddleware(req: Request, res: Response, next: NextFunction) {
console.log(`Request: ${req.method} ${req.url}`);
next();
}
export default loggerMiddleware;
See lihtne vahevara logib päringu meetodi ja URL-i konsooli. Analüüsime tüübi annotatsioone:
Request: Tähistab Expressi päringu objekti.Response: Tähistab Expressi vastuse objekti.NextFunction: Funktsioon, mis käivitatakse järgmise vahevara magasinis.
Saate seda vahevara oma Expressi rakenduses kasutada järgmiselt:
import express from 'express';
import loggerMiddleware from './middleware/loggerMiddleware';
const app = express();
const port = 3000;
app.use(loggerMiddleware);
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
Täiustatud tüübimustrid vahevara jaoks
Kuigi põhiline vahevara näide on funktsionaalne, puudub sellel paindlikkus ja tüübikindlus keerukamate stsenaariumide jaoks. Uurime täiustatud tüübimustreid, mis täiustavad vahevara arendust TypeScriptiga.
1. Kohandatud päringu/vastuse tüübid
Sageli peate laiendama objekte Request või Response kohandatud omadustega. Näiteks pärast autentimist võite soovida lisada objektile Request omaduse user. TypeScript võimaldab teil olemasolevaid tüüpe suurendada deklaratsiooni ühendamise abil.
// src/types/express/index.d.ts
import { Request as ExpressRequest } from 'express';
declare global {
namespace Express {
interface Request {
user?: {
id: string;
email: string;
// ... other user properties
};
}
}
}
export {}; // This is needed to make the file a module
Selles näites suurendame liidest Express.Request, et lisada valikuline omadus user. Nüüd saate oma autentimise vahevaras selle omaduse täita:
import { Request, Response, NextFunction } from 'express';
function authenticationMiddleware(req: Request, res: Response, next: NextFunction) {
// Simulate authentication logic
const userId = req.headers['x-user-id'] as string; // Or fetch from a token, etc.
if (userId) {
// In a real application, you would fetch the user from a database
req.user = {
id: userId,
email: `user${userId}@example.com`
};
next();
} else {
res.status(401).send('Unauthorized');
}
}
export default authenticationMiddleware;
Ja oma marsruudi haldurites saate turvaliselt juurde pääseda omadusele req.user:
import express from 'express';
import authenticationMiddleware from './middleware/authenticationMiddleware';
const app = express();
const port = 3000;
app.use(authenticationMiddleware);
app.get('/profile', (req: Request, res: Response) => {
if (req.user) {
res.send(`Hello, ${req.user.email}! Your user ID is ${req.user.id}`);
} else {
// This should never happen if the middleware is working correctly
res.status(500).send('Internal Server Error');
}
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
2. Vahevara tehased
Vahevara tehased on funktsioonid, mis tagastavad vahevara funktsioone. See muster on kasulik, kui peate vahevara konfigureerima konkreetsete valikute või sõltuvustega. Näiteks kaaluge logimise vahevara, mis logib sõnumeid konkreetsele failile:
import { Request, Response, NextFunction } from 'express';
import fs from 'fs';
import path from 'path';
function createLoggingMiddleware(logFilePath: string) {
return (req: Request, res: Response, next: NextFunction) => {
const logMessage = `[${new Date().toISOString()}] Request: ${req.method} ${req.url}\n`;
fs.appendFile(logFilePath, logMessage, (err) => {
if (err) {
console.error('Error writing to log file:', err);
}
next();
});
};
}
export default createLoggingMiddleware;
Saate seda vahevara tehast kasutada järgmiselt:
import express from 'express';
import createLoggingMiddleware from './middleware/loggingMiddleware';
const app = express();
const port = 3000;
const logFilePath = path.join(__dirname, 'logs', 'requests.log');
app.use(createLoggingMiddleware(logFilePath));
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
3. Asünkroonne vahevara
Vahevara funktsioonid peavad sageli sooritama asünkroonseid toiminguid, nagu andmebaasi päringud või API-kõned. Asünkroonsete toimingute korrektseks käsitlemiseks peate tagama, et funktsioon next kutsutakse pärast asünkroonse toimingu lõpetamist. Saate seda saavutada kasutades async/await või lubadusi.
import { Request, Response, NextFunction } from 'express';
async function asyncMiddleware(req: Request, res: Response, next: NextFunction) {
try {
// Simulate an asynchronous operation
await new Promise(resolve => setTimeout(resolve, 100));
console.log('Asynchronous operation completed');
next();
} catch (error) {
next(error); // Pass the error to the error handling middleware
}
}
export default asyncMiddleware;
Oluline: Ärge unustage käsitleda vigu oma asünkroonses vahevaras ja edastada need veakäsitlusvahevarale, kasutades next(error). See tagab, et vigu käsitletakse ja logitakse korrektselt.
4. Veakäsitlusvahevara
Veakäsitlusvahevara on spetsiaalne vahevara tüüp, mis käsitleb vigu, mis tekivad päringu-vastuse tsükli ajal. Veakäsitlusvahevara funktsioonidel on neli argumenti: err, req, res ja next.
import { Request, Response, NextFunction } from 'express';
function errorHandler(err: any, req: Request, res: Response, next: NextFunction) {
console.error(err.stack);
res.status(500).send('Something went wrong!');
}
export default errorHandler;
Peate registreerima veakäsitlusvahevara pärast kõiki teisi vahevara ja marsruudi haldureid. Express tuvastab veakäsitlusvahevara nelja argumendi olemasolu järgi.
import express from 'express';
import asyncMiddleware from './middleware/asyncMiddleware';
import errorHandler from './middleware/errorHandler';
const app = express();
const port = 3000;
app.use(asyncMiddleware);
app.get('/', (req, res) => {
throw new Error('Simulated error!'); // Simulate an error
});
app.use(errorHandler); // Error handling middleware MUST be registered last
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
5. Päringu valideerimise vahevara
Päringu valideerimine on turvaliste ja usaldusväärsete API-de loomise oluline aspekt. Vahevara saab kasutada sissetulevate päringu andmete valideerimiseks ja tagamaks, et see vastab teatud kriteeriumitele, enne kui see jõuab teie marsruudi halduriteni. Päringu valideerimiseks saab kasutada teeke nagu joi või express-validator.
Siin on näide kasutades express-validator:
import { Request, Response, NextFunction } from 'express';
import { body, validationResult } from 'express-validator';
const validateCreateUserRequest = [
body('email').isEmail().normalizeEmail(),
body('password').isLength({ min: 8 }),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next();
}
];
export default validateCreateUserRequest;
See vahevara valideerib päringu kehas väljad email ja password. Kui valideerimine ebaõnnestub, tagastab see 400 Bad Request vastuse koos veateadete massiiviga. Saate seda vahevara oma marsruudi haldurites kasutada järgmiselt:
import express from 'express';
import validateCreateUserRequest from './middleware/validateCreateUserRequest';
const app = express();
const port = 3000;
app.post('/users', validateCreateUserRequest, (req, res) => {
// If validation passes, create the user
res.send('User created successfully!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
6. Sõltuvuse süstimine vahevarale
Kui teie vahevara funktsioonid sõltuvad välistest teenustest või konfiguratsioonidest, aitab sõltuvuse süstimine parandada testitavust ja hooldatavust. Saate kasutada sõltuvuse süstimise konteinerit nagu tsyringe või lihtsalt edastada sõltuvusi argumentidena oma vahevara tehastele.
Siin on näide kasutades vahevara tehast koos sõltuvuse süstimisega:
// src/services/UserService.ts
export class UserService {
async createUser(email: string, password: string): Promise {
// In a real application, you would save the user to a database
console.log(`Creating user with email: ${email} and password: ${password}`);
await new Promise(resolve => setTimeout(resolve, 500)); // Simulate a database operation
}
}
// src/middleware/createUserMiddleware.ts
import { Request, Response, NextFunction } from 'express';
import { UserService } from '../services/UserService';
function createCreateUserMiddleware(userService: UserService) {
return async (req: Request, res: Response, next: NextFunction) => {
try {
const { email, password } = req.body;
await userService.createUser(email, password);
res.status(201).send('User created successfully!');
} catch (error) {
next(error);
}
};
}
export default createCreateUserMiddleware;
// src/app.ts
import express from 'express';
import createCreateUserMiddleware from './middleware/createUserMiddleware';
import { UserService } from './services/UserService';
import errorHandler from './middleware/errorHandler';
const app = express();
const port = 3000;
app.use(express.json()); // Parse JSON request bodies
const userService = new UserService();
const createUserMiddleware = createCreateUserMiddleware(userService);
app.post('/users', createUserMiddleware);
app.use(errorHandler);
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
Parimad tavad TypeScripti vahevara jaoks
- Hoidke vahevara funktsioonid väikesed ja fokuseeritud. Igal vahevara funktsioonil peaks olema üks vastutus.
- Kasutage oma vahevara funktsioonide jaoks kirjeldavaid nimesid. Nimi peaks selgelt näitama, mida vahevara teeb.
- Käsitlege vigu korrektselt. Püüdke alati kinni vead ja edastage need veakäsitlusvahevarale, kasutades
next(error). - Kasutage kohandatud päringu/vastuse tüüpe, et suurendada tüübikindlust. Suurendage liideseid
RequestjaResponsevastavalt vajadusele kohandatud omadustega. - Kasutage vahevara tehaseid, et konfigureerida vahevara konkreetsete valikutega.
- Dokumenteerige oma vahevara funktsioonid. Selgitage, mida vahevara teeb ja kuidas seda tuleks kasutada.
- Testige oma vahevara funktsioone põhjalikult. Kirjutage ühikuteste, et tagada oma vahevara funktsioonide korrektne toimimine.
Järeldus
TypeScript suurendab oluliselt Expressi vahevara arendust, lisades staatilise tüübi, parandades koodi hooldatavust ja tuvastades vead varakult. Valdades täiustatud tüübimustreid nagu kohandatud päringu/vastuse tüübid, vahevara tehased, asünkroonne vahevara, veakäsitlusvahevara ja päringu valideerimise vahevara, saate luua tugevaid, skaleeritavaid ja tüübikindlaid Expressi rakendusi. Ärge unustage järgida parimaid tavasid, et hoida oma vahevara funktsioonid väikesed, fokuseeritud ja hästi dokumenteeritud.